
#include <ast.h>
#include <lexer.h>
#include <generator.h>
#include <iostream>

#define MAKE_GEN(__type) do { if (stat.type() == typeid(__type)) return std::any_cast<__type>(stat).gen(g); } while (0)

void generateStat(Generator *g, Stat stat) {
  if (!stat.has_value()) return;
  MAKE_GEN(NameStat);
  MAKE_GEN(BlockStat);
  MAKE_GEN(ReturnStat);
  MAKE_GEN(IfStat);
  MAKE_GEN(UnaryOpStat);
  MAKE_GEN(BinaryOpStat);
  MAKE_GEN(TernaryOpStat);
  MAKE_GEN(NameStat);
  MAKE_GEN(LiteralIntegerStat);
  MAKE_GEN(ForStat);
  MAKE_GEN(ParamStat);
  MAKE_GEN(FunctionStat);
  MAKE_GEN(VariableDefineStat);
  MAKE_GEN(VariableStat);
  MAKE_GEN(StructStat);
  MAKE_GEN(VarStat);

  MAKE_GEN(WhileStat);
  MAKE_GEN(DoWhileStat);
  MAKE_GEN(GotoStat);
  MAKE_GEN(ContinueStat);
  MAKE_GEN(BreakStat);

  MAKE_GEN(LabelStat);

  panic("Unknown stat type");
}

#define MAKE_TYPE(__type) do { if (stat.type() == typeid(__type)) return k##__type; } while (0)
StatType statType(Stat stat) {
  MAKE_TYPE(EmptyStat);
  MAKE_TYPE(SwitchStat);
  MAKE_TYPE(CaseStat);
  MAKE_TYPE(IfStat);
  MAKE_TYPE(WhileStat);
  MAKE_TYPE(DoWhileStat);
  MAKE_TYPE(ForStat);
  MAKE_TYPE(LabelStat);
  MAKE_TYPE(BreakStat);
  MAKE_TYPE(ContinueStat);
  MAKE_TYPE(LiteralIntegerStat);
  MAKE_TYPE(LiteralCharStat);
  MAKE_TYPE(LiteralFloatStat);
  MAKE_TYPE(LiteralStringStat);
  MAKE_TYPE(UnaryOpStat);
  MAKE_TYPE(BinaryOpStat);
  MAKE_TYPE(TernaryOpStat);
  MAKE_TYPE(FuncCallArgsStat);
  MAKE_TYPE(BlockStat);
  MAKE_TYPE(NameStat);

  panic("Unknown stat type");
  return kNoneStat;
}

void BlockStat::gen(Generator *g) {g->gen(this);}
void LiteralIntegerStat::gen(Generator *g) { g->gen(this);}
void NameStat::gen(Generator *g) { g->gen(this);}
void ReturnStat::gen(Generator *g) {g->gen(this);}
void IfStat::gen(Generator *g) { g->gen(this);}
void ForStat::gen(Generator *g) { g->gen(this);}
void UnaryOpStat::gen(Generator *g) { g->gen(this);}
void BinaryOpStat::gen(Generator *g) { g->gen(this);}
void TernaryOpStat::gen(Generator *g) { g->gen(this);}

void StructStat::gen(Generator *g) { g->gen(this);}

void VarStat::gen(Generator *g) {g->gen(this);}

void FunctionStat::gen(Generator *g) { g->gen(this);}
void ParamStat::gen(Generator *g) { g->gen(this);}
void VariableDefineStat::gen(Generator *g) { g->gen(this);}
void VariableStat::gen(Generator *g) { g->gen(this);}

void GotoStat::gen(Generator *g) { g->gen(this);}
void ContinueStat::gen(Generator *g) { g->gen(this);}
void BreakStat::gen(Generator *g) { g->gen(this);}
void WhileStat::gen(Generator *g) { g->gen(this);}
void DoWhileStat::gen(Generator *g) { g->gen(this);}
void LabelStat::gen(Generator *g) { g->gen(this);}


